package ffte.test.types

import spinal.core._
import spinal.core.sim._
import ffte.types._

/**
 * 真正简单的FFTE类型示例 - 修正所有硬件错误
 */
class TrulySimpleExample extends Component {
  val io = new Bundle {
    val input = in SInt(16 bits)
    val output = out SInt(16 bits)
    val enable = in Bool()
  }

  val testArea = new Area {
    // 创建FixReal实例
    val myFixReal = FixReal(16, -8)
    val resultFixReal = FixReal(16, -8)
    
    // 必须始终为FixReal的内部信号赋值，避免锁存器
    myFixReal.d.raw := io.input
    
    // 创建加法硬件
    val doubled = myFixReal + myFixReal
    
    // 根据使能信号选择输出
    resultFixReal.d.raw := doubled.d.raw
    
    // 连接输出 - 确保所有路径都被覆盖
    io.output := resultFixReal.d.raw
  }
}

/**
 * 修正的FixReal本质演示
 */
class FixRealCorrectDemo extends Component {
  val io = new Bundle {
    val in1 = in SInt(16 bits)
    val in2 = in SInt(16 bits)
    val out_add = out SInt(16 bits)
    val out_mul = out SInt(32 bits)  // 乘法需要更大宽度
    val out_resize = out SInt(24 bits)
  }

  val demoArea = new Area {
    // 创建FixReal实例
    val a = FixReal(16, -8)
    val b = FixReal(16, -8)
    val sum = FixReal(16, -8)
    val product = FixReal(32, -16)  // 乘积需要更大的位宽
    val resized = FixReal(24, -8)
    
    // 始终连接输入
    a.d.raw := io.in1
    b.d.raw := io.in2
    
    // 创建硬件运算
    val sumResult = a + b
    val productResult = a * b
    val resizedResult = a.resize(24)
    
    // 连接结果
    sum.d.raw := sumResult.d.raw
    product.d.raw := productResult.d.raw
    resized.d.raw := resizedResult.d.raw
    
    // 连接输出
    io.out_add := sum.d.raw
    io.out_mul := product.d.raw
    io.out_resize := resized.d.raw
  }
}

/**
 * 仿真测试
 */
object TrulySimpleExampleSim {
  def main(args: Array[String]): Unit = {
    SimConfig.withWave.compile(new TrulySimpleExample()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      println("开始TrulySimpleExample仿真...")
      
      // 测试1: 基本加法
      dut.io.enable #= true
      dut.io.input #= Math.round(0.5 * 128)
      dut.clockDomain.waitSampling(1)
      
      val output1 = dut.io.output.toInt
      println(f"测试1: 输入0.5，输出$output1，期望${Math.round(1.0 * 128)}")
      
      // 测试2: 不同输入
      dut.io.input #= Math.round(0.25 * 128)
      dut.clockDomain.waitSampling(1)
      
      val output2 = dut.io.output.toInt
      println(f"测试2: 输入0.25，输出$output2，期望${Math.round(0.5 * 128)}")
      
      println("基础仿真完成！")
    }
    
    // 运行第二个演示
    SimConfig.withWave.compile(new FixRealCorrectDemo()).doSim { dut =>
      dut.clockDomain.forkStimulus(period = 10)
      
      println("\n开始FixRealCorrectDemo仿真...")
      
      // 测试不同的操作
      dut.io.in1 #= Math.round(0.5 * 128)
      dut.io.in2 #= Math.round(0.3 * 128)
      dut.clockDomain.waitSampling(1)
      
      val addResult = dut.io.out_add.toInt
      val mulResult = dut.io.out_mul.toInt
      val resizeResult = dut.io.out_resize.toInt
      
      println(f"输入1: 0.5 (${0.5 * 128}), 输入2: 0.3 (${0.3 * 128})")
      println(f"加法结果: $addResult (${addResult / 128.0})")
      println(f"乘法结果: $mulResult (${mulResult / (128.0 * 128.0)})")
      println(f"调整大小结果: $resizeResult (${resizeResult / 128.0})")
      
      println("\n关键观察：")
      println(s"1. FixReal是硬件信号，.d.raw访问底层表示")
      println(s"2. 运算创建实际硬件（加法器、乘法器）")
      println(s"3. 位宽管理是硬件设计的重要部分")
      println(s"4. 仿真显示的是硬件信号行为")
      
      println("\n仿真完成！")
    }
  }
}